import json
import datetime
from django.db import models
from django.contrib.auth.models import User
from ziping.bazi import bazi_by_date, bazi_by_sizhu


class UserInfo(models.Model):
    class Meta:
        verbose_name = '用户信息'
        verbose_name_plural = '用户信息'

    user = models.ForeignKey(User, verbose_name='用户', on_delete=models.SET_NULL, null=True, blank=True)
    nickname = models.CharField(verbose_name='昵称', max_length=128)
    avatar = models.CharField(verbose_name='头像', max_length=255)
    openid = models.CharField(verbose_name='openid', max_length=128)
    unionid = models.CharField(verbose_name='unionid', max_length=128)
    created_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    last_modified = models.DateTimeField(verbose_name='变更时间', auto_now=True)
    detail = models.TextField(verbose_name='详情', default='', blank=True)

    def __str__(self):
        return self.nickname

    def to_json(self):
        return {
            'nickname': self.nickname,
            'openid': self.openid,
            'avatar': self.avatar,
        }


class UserPan(models.Model):
    class Meta:
        verbose_name = '用户排盘'
        verbose_name_plural = '用户排盘'

    user = models.ForeignKey(User, verbose_name='用户', on_delete=models.SET_NULL, null=True, blank=True)
    name = models.CharField(verbose_name='报告姓名', max_length=128)
    gender = models.CharField(verbose_name='性别', max_length=16)
    input = models.CharField(verbose_name='输入', max_length=128)
    report = models.TextField(verbose_name='报告json')
    tags = models.TextField(verbose_name='标签', default='', blank=True)
    created_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    last_modified = models.DateTimeField(verbose_name='变更时间', auto_now=True)
    views = models.IntegerField(verbose_name='查看次数', default=0)
    is_delete = models.BooleanField(verbose_name='是否删除', default=False)

    def __str__(self):
        return self.name

    def rebuild_mp(self):
        gender = 'male' if self.gender == '男' else 'female'
        params = self.input.split()
        if len(params) == 4:
            mp = bazi_by_sizhu(params, gender)
        else:
            if len(params) == 3:
                date_type = 'Solar' if params[0] == '阳历' else 'Lunar'
                birthday = datetime.datetime.strptime(f'{params[1]} {params[2]}', '%Y-%m-%d %H:%M')
            else:
                date_type = 'Solar'
                birthday = datetime.datetime.strptime(self.input, '%Y-%m-%d %H:%M')
            mp = bazi_by_date(
                birthday.year,
                birthday.month,
                birthday.day,
                birthday.hour,
                birthday.minute,
                gender,
                date_type,
            )
        return mp

    def refresh(self):
        mp = self.rebuild_mp()
        self.report = json.dumps(mp.to_json())
        self.save()

    def my_tags(self):
        if not self.tags:
            mp = self.rebuild_mp()
            self.tags = json.dumps(mp.calc_tags())
            self.save()
        return json.loads(self.tags)

    def explanation(self):
        _DEFAULT = '敬请期待'
        tags = self.my_tags()
        ans = [
            {
                'category': '格局',
                'title': tags['格局'],
                'content': Geju.objects.get(name=tags['格局']).desc or _DEFAULT
            }, {
                'category': '日干月建',
                'title': tags['日干月建'],
                'content': YuanAtMonth.objects.get(name=tags['日干月建']).desc or _DEFAULT
            }, {
                'category': '最强五行',
                'title': f"最强·{tags['最强五行']}",
                'content': Wuxing.objects.get(name=tags['最强五行']).overflow_desc or _DEFAULT
            }, {
                'category': '最弱五行',
                'title': f"最弱·{tags['最弱五行']}",
                'content': Wuxing.objects.get(name=tags['最弱五行']).underflow_desc or _DEFAULT
            }
        ]
        for item in tags['天干十神组合']:
            ans.append({
                'category': '天干十神组合',
                'title': item,
                'content': ShiShenCombine.objects.get(name=item).desc or _DEFAULT
            })
        for item in tags['宫位十神组合']:
            ans.append({
                'category': '宫位十神组合',
                'title': item,
                'content': ShiShenAtHouse.objects.get(name=item).desc or _DEFAULT
            })
        return ans

    def to_json(self):
        return {
            'id': self.id,
            'name': self.name,
            'gender': self.gender,
            'input': self.input,
            'report': json.loads(self.report),
            'created_time': self.created_time.strftime('%Y-%m-%d %H:%M:%S'),
            'last_modified': self.last_modified.strftime('%Y-%m-%d %H:%M:%S'),
            'views': self.views,
        }


class House(models.Model):
    class Meta:
        verbose_name = '宫位'
        verbose_name_plural = '宫位'

    name = models.CharField(verbose_name='名称', max_length=8)
    x = models.SmallIntegerField(verbose_name='第几柱')
    y = models.SmallIntegerField(verbose_name='天干还是地支')

    def __str__(self):
        return self.name

    @classmethod
    def create_houses(cls):
        data = [
            {'name': '年干', 'x': 0, 'y': 0},
            {'name': '年支', 'x': 0, 'y': 1},
            {'name': '月干', 'x': 1, 'y': 0},
            {'name': '月支', 'x': 1, 'y': 1},
            {'name': '日干', 'x': 2, 'y': 0},
            {'name': '日支', 'x': 2, 'y': 1},
            {'name': '时干', 'x': 3, 'y': 0},
            {'name': '时支', 'x': 3, 'y': 1},
        ]
        for item in data:
            cls.objects.create(**item)


class ShiShen(models.Model):
    class Meta:
        verbose_name = '十神'
        verbose_name_plural = '十神'

    name = models.CharField(verbose_name='名称', max_length=8)
    rule = models.CharField(verbose_name='规则说明', max_length=64)
    desc = models.TextField(verbose_name='描述', blank=True, default='')

    def __str__(self):
        return self.name

    @classmethod
    def create_shishens(cls):
        data = [
            {'name': '劫财', 'rule': '五行相同阴阳不同'},
            {'name': '比肩', 'rule': '五行相同阴阳相同'},
            {'name': '伤官', 'rule': '五行我生阴阳不同'},
            {'name': '食神', 'rule': '五行我生阴阳相同'},
            {'name': '正财', 'rule': '五行我克阴阳不同'},
            {'name': '偏财', 'rule': '五行我克阴阳相同'},
            {'name': '正官', 'rule': '五行克我阴阳不同'},
            {'name': '七杀', 'rule': '五行克我阴阳相同'},
            {'name': '正印', 'rule': '五行生我阴阳不同'},
            {'name': '偏印', 'rule': '五行生我阴阳相同'},
        ]
        for item in data:
            cls.objects.create(**item)


class ShiShenAtHouse(models.Model):
    class Meta:
        verbose_name = '十神宫位组合'
        verbose_name_plural = '十神宫位组合'

    name = models.CharField(verbose_name='名称', max_length=16)
    house = models.ForeignKey(House, verbose_name='宫位', on_delete=models.CASCADE)
    shishen = models.ForeignKey(ShiShen, verbose_name='十神', on_delete=models.CASCADE)
    abbr = models.CharField(verbose_name='简述', max_length=255)
    desc = models.TextField(verbose_name='详细描述', blank=True, default='')

    def __str__(self):
        return self.name

    @classmethod
    def create_records(cls):
        for h in House.objects.all():
            for ss in ShiShen.objects.all():
                if not h.name == '日干':
                    cls.objects.create(
                        name=f'{h.name}·{ss.name}',
                        house=h,
                        shishen=ss
                    )


class ShenSha(models.Model):
    class Meta:
        verbose_name = '神煞'
        verbose_name_plural = '神煞'

    name = models.CharField(verbose_name='名称', max_length=64)
    abbr = models.TextField(verbose_name='口诀', blank=True, default='')
    rule = models.TextField(verbose_name='查法', blank=True, default='')
    desc = models.TextField(verbose_name='含义', blank=True, default='')

    def __str__(self):
        return self.name

    def to_json(self):
        return {
            'name': self.name,
            'abbr': self.abbr,
            'rule': self.rule,
            'desc': self.desc,
        }


class Wuxing(models.Model):
    class Meta:
        verbose_name = '五行'
        verbose_name_plural = '五行'

    name = models.CharField(verbose_name='名称', max_length=4)
    basic_desc = models.TextField(verbose_name='基础含义', blank=True, default='')
    overflow_desc = models.TextField(verbose_name='太强负面含义', blank=True, default='')
    underflow_desc = models.TextField(verbose_name='太弱负面含义', blank=True, default='')

    def __str__(self):
        return self.name


class Geju(models.Model):
    class Meta:
        verbose_name = '格局'
        verbose_name_plural = '格局'

    name = models.CharField(verbose_name='名称', max_length=32)
    category = models.CharField(verbose_name='分类', max_length=32)
    desc = models.TextField(verbose_name='含义', blank=True, default='')

    def __str__(self):
        return self.name

    @classmethod
    def create_gejus(cls):
        data = [
            ('专旺格', '曲直格/炎上格/稼穑格/从革格/润下格'),
            ('从格', '从财格/从杀格/从儿格/从旺格/从强格'),
            ('化格', '化木格/化火格/化土格/化金格/化水格'),
            ('禄刃格', '建禄格/月刃格'),
            ('普通格', '正印格/偏印格/食神格/伤官格/正财格/偏财格/七杀格/正官格'),
        ]
        for cate, items in data:
            for name in items.split('/'):
                cls.objects.create(category=cate, name=name)


class YuanAtMonth(models.Model):
    class Meta:
        verbose_name = '日干月建'
        verbose_name_plural = '日干月建'

    name = models.CharField(verbose_name='名称', max_length=32)
    gan = models.CharField(verbose_name='日主（日干）', max_length=8)
    zhi = models.CharField(verbose_name='月建（月支）', max_length=8)
    desc = models.TextField(verbose_name='含义', blank=True, default='')

    def __str__(self):
        return self.name

    @classmethod
    def create_records(cls):
        gans = '甲乙丙丁戊己庚辛壬癸'
        zhis = '子丑寅卯辰巳午未申酉戌亥'
        for gan in gans:
            for zhi in zhis:
                cls.objects.create(
                    name=f'{gan}生{zhi}月',
                    gan=gan,
                    zhi=zhi,
                )


class ShiShenCombine(models.Model):
    class Meta:
        verbose_name = '十神组合'
        verbose_name_plural = '十神组合'

    name = models.CharField(verbose_name='名称', max_length=32)
    desc = models.TextField(verbose_name='含义', blank=True, default='')

    def __str__(self):
        return self.name

    @classmethod
    def create_combines(cls):
        data = [
            {'name': '枭印夺食', 'desc': ''},
            {'name': '食伤生财', 'desc': ''},
            {'name': '财破印',   'desc': ''},
            {'name': '食神制杀', 'desc': ''},
            {'name': '伤官见官', 'desc': ''},
            {'name': '官杀混杂', 'desc': ''},
            {'name': '财官相生', 'desc': ''},
            {'name': '官印相生', 'desc': ''},
            {'name': '比肩分财', 'desc': ''},
            {'name': '比劫重重', 'desc': ''},
        ]
        for item in data:
            cls.objects.create(**item)


class FeedBack(models.Model):
    class Meta:
        verbose_name = '反馈'
        verbose_name_plural = '反馈'

    user = models.ForeignKey(User, verbose_name='用户', on_delete=models.SET_NULL, null=True, blank=True)
    content = models.TextField(verbose_name='反馈内容')
    created_time = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.content[:20]
